/*
 * QWUPClient.cpp
 *
 *  Created on: 2009-9-15
 *      Author: bingkai
 */
#include "QDownloadStoreFile.h"
#include "CommonFile.h"
#include "QFile.h"
#include "QTextSetting.h"
#include "QDateTime.h"
#include "QWString.h"
#include "QSString.h"

#include "AddonBookCityStub.h"
#include "DownloadManager.h"
#include "DownloadOperator.h"
#include "cx_string.h"
#include "cx_memory.h"
#include "reader_model_bookstore.h"
#include "Profiler.h"
#include "QInstance.h"
#include "cx_typedef.h"
#include "cx_tinydb.h"
#include "cx_debug.h"

enum ETypeOfData
    {
    	eTypeQInt32,
        eTypeQUInt32,
        eTypeQWString,
        eTypeQDateTime,
        eTypeQUInt16,
        eTypeQInt16,
        eTypeQBOOL
    };

CQDownloadStoreFile::CQDownloadStoreFile() :
	iDirType(E_COMMEN)
{
	// TODO Auto-generated constructor stub

}

CQDownloadStoreFile::~CQDownloadStoreFile()
{
	// TODO Auto-generated destructor stub
}

void CQDownloadStoreFile::init()
{
	iBookDownloadInfodb = CXTinydbMgr_create();
	SetConfigType(CQDownloadStoreFile::E_READER_ONLINE_LIST);
	CQWString strfilename = GetFilePath();
	strfilename.AppendData((LPCWSTR)CX_T(".tdb"));
	iBookDownloadInfodb->open(iBookDownloadInfodb,strfilename.GetDataPtr(),modeReadWrite,0);

}

void CQDownloadStoreFile::uninit()
{
	if(iBookDownloadInfodb)
	{
		iBookDownloadInfodb->close(iBookDownloadInfodb);
		CXTinydbMgr_release(iBookDownloadInfodb);
		iBookDownloadInfodb = NULL;
	}
}

int inline findall2 (const void * pValue,unsigned int vlen)
{
	return 1;
}

void AppendQWString2(CQSString& data,CQWString& string)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQWString;
	data.AppendData((QPBYTE)&type,4);
	len = string.GetLength()*2;
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)string.GetDataPtr(),len);
}

void AppendQUInt322(CQSString& data,QUINT32 value)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQUInt32;
	data.AppendData((QPBYTE)&type,4);
	len = sizeof(value);
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)&value,len);
}

void AppendQBOOL2(CQSString& data,QBOOL value)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQBOOL;
	data.AppendData((QPBYTE)&type,4);
	len = sizeof(value);
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)&value,len);
}

void AppendQInt322(CQSString& data,QINT32 value)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQInt32;
	data.AppendData((QPBYTE)&type,4);
	len = sizeof(value);
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)&value,len);
}

void AppendQDateTime2(CQSString& data,QDateTime& value)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQDateTime;
	data.AppendData((QPBYTE)&type,4);
	QTime time;
	time.wYear = 0;
	time.nMonth = 0;
	time.nDay = 0;
	time.nHour = 0;
	time.nMin = 0;
	time.nSec = 0;
	time.nMicroSec = 0;
	
	value.GetTime(&time);
	len = sizeof(time.wYear)+sizeof(time.nMonth)+sizeof(time.nDay)+sizeof(time.nHour)
			+sizeof(time.nMin)+sizeof(time.nSec)/*+sizeof(time.nMicroSec)*/;
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)&time.wYear,sizeof(time.wYear));
	data.AppendData((QPBYTE)&time.nMonth,sizeof(time.nMonth));
	data.AppendData((QPBYTE)&time.nDay,sizeof(time.nDay));
	data.AppendData((QPBYTE)&time.nHour,sizeof(time.nHour));
	data.AppendData((QPBYTE)&time.nMin,sizeof(time.nMin));
	data.AppendData((QPBYTE)&time.nSec,sizeof(time.nSec));
}

void AppendQUInt162(CQSString& data,QUINT16 value)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQUInt16;
	data.AppendData((QPBYTE)&type,4);
	len = sizeof(value);
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)&value,len);
}

void AppendQInt162(CQSString& data,QINT16 value)
{
	ETypeOfData type;
	unsigned int len = 0;
	type = eTypeQInt16;
	data.AppendData((QPBYTE)&type,4);
	len = sizeof(value);
	data.AppendData((QPBYTE)&len,4);
	data.AppendData((QPBYTE)&value,len);
}

void PutDownloadInfoData(CXTinydbMgr* pBookDownloadInfodb,download_operator_data_t& opdata)
{
	if(opdata.dirty)
	{
		const unsigned short* pKey = opdata.filename;
		unsigned int keylen = cx_strlen(opdata.filename)*2;
		CQSString data;
		CQWString wStr;		
		//save progress
		AppendQUInt322(data,opdata.pageid);		
		//save id
		wStr.Empty();
		if(opdata.url)
		{
			wStr.AppendData((LPCWSTR)opdata.url,cx_strlen_w((LPCWSTR)opdata.url));
			AppendQWString2(data,wStr);
		}
		wStr.Empty();
		if(opdata.actualurl)
		{
			wStr.AppendData((LPCWSTR)opdata.actualurl,cx_strlen_w((LPCWSTR)opdata.actualurl));
			AppendQWString2(data,wStr);
		}		
		wStr.Empty();
		if(opdata.filename)
		{
			wStr.AppendData((LPCWSTR)opdata.filename,cx_strlen_w((LPCWSTR)opdata.filename));
			AppendQWString2(data,wStr);
		}		
		wStr.Empty();
		if(opdata.bookid)
		{
			wStr.AppendData((LPCWSTR)opdata.bookid,cx_strlen_w((LPCWSTR)opdata.bookid));
			AppendQWString2(data,wStr);
		}		
		//save chapterid
		AppendQUInt162(data,opdata.chapterid);		
		//save maxchapter
		AppendQUInt162(data,opdata.maxchapter);
		
		//save offset
		AppendQUInt322(data,opdata.offset);
		
		//save receivenumber
		AppendQUInt322(data,opdata.receivenumber);
		
		//save onereceivenumber
		AppendQUInt322(data,opdata.onereceivenumber);
		
		//save totalnumber
		AppendQUInt322(data,opdata.totalnumber);
		
		//save downstatus
		AppendQUInt162(data,opdata.downstatus);
					
		char* pData = data.GetDataPtr();
		unsigned int datalen = data.GetLength();
		pBookDownloadInfodb->put(pBookDownloadInfodb,pKey,keylen,pData,datalen,0,0,eTinydb_Put_AddReplace);
		opdata.dirty = 0;
	}
}

QBOOL ReadOneDonwloadInfo(char* val,unsigned int len,download_operator_data_t& download_operator)
{
	QBOOL ret = QFALSE;
	cx_memset(&download_operator,0,sizeof(download_operator));
	
	unsigned int pos = 0;
	char* p = val;
	unsigned int type; 
	unsigned int vlen;
	unsigned int num = 0;
	int run = 1;
	CQWString str;
	while(len-pos>8&&run)
	{
		cx_memcpy(&type,p+pos,4);
		pos += 4;
		cx_memcpy(&vlen,p+pos,4);
		pos += 4;
		switch(num)
		{
		case 0:
			if(eTypeQUInt32==type)
			{
				cx_memcpy(&download_operator.pageid,p+pos,4);
			}
			else
				run = 0;
			break;
		case 1:
			if(eTypeQWString==type)
			{
				str.SetData((unsigned short*)(p+pos),vlen/2);
				copy_string_w(&(download_operator.url),(unsigned short*)(str.GetDataPtr()));
			}
			else
				run = 0;
			break;
		case 2:
			if(eTypeQWString==type)
			{
				str.SetData((unsigned short*)(p+pos),vlen/2);
				copy_string_w(&(download_operator.actualurl),(unsigned short*)(str.GetDataPtr()));
			}
			else
				run = 0;
			break;	
		case 3:
			if(eTypeQWString==type)
			{
				str.SetData((unsigned short*)(p+pos),vlen/2);
				copy_string_w(&(download_operator.filename),(unsigned short*)(str.GetDataPtr()));
			}
			else
				run = 0;
			break;	
		case 4:
			if(eTypeQWString==type)
			{
				str.SetData((unsigned short*)(p+pos),vlen/2);
				copy_string_w(&(download_operator.bookid),(unsigned short*)(str.GetDataPtr()));
			}
			else
				run = 0;
			break;	
		case 5:
			if(eTypeQUInt16==type)
			{
				cx_memcpy(&download_operator.chapterid,p+pos,2);
			}
			else
				run = 0;
			break;
		case 6:
			if(eTypeQUInt16==type)
			{
				cx_memcpy(&download_operator.maxchapter,p+pos,2);
			}
			else
				run = 0;
			break;
		case 7:
			if(eTypeQUInt32==type)
			{
				cx_memcpy(&download_operator.offset,p+pos,4);
			}
			else
				run = 0;
			break;
		case 8:
			if(eTypeQUInt32==type)
			{
				cx_memcpy(&download_operator.receivenumber,p+pos,4);
			}
			else
				run = 0;
			break;
		case 9:
			if(eTypeQUInt32==type)
			{
				cx_memcpy(&download_operator.onereceivenumber,p+pos,4);
			}
			else
				run = 0;	
			break;
		case 10:
			if(eTypeQUInt32==type)
			{
				cx_memcpy(&download_operator.totalnumber,p+pos,4);
			}
			else
				run = 0;
			break;
		case 11:
			if(eTypeQUInt16==type)
			{
				cx_memcpy(&download_operator.downstatus,p+pos,2);
			}
			else
				run = 0;
			break;	
		}
		pos += vlen;
		num ++;
	}
	if(run==1||num!=12)
	{
		ret = QTRUE;
	}
	return ret;
}

void CQDownloadStoreFile::GetDownloadInfoList(ADDON_REF(IObject) thiz)
{
	SetConfigType(CQDownloadStoreFile::E_READER_WORK_DOWNLOAD_LIST);
	
	//read from tiny db
	iBookDownloadInfodb->mapdata(iBookDownloadInfodb);
	int nCount = iBookDownloadInfodb->findbydata(iBookDownloadInfodb,findall2);
	int i = 0;
	iBookDownloadInfodb->movedatacursortofirst(iBookDownloadInfodb);
	char *val = NULL;
	unsigned int  len = 0;
	download_operator_data_t download_operator;
	for(i = 0;i < nCount;i++)
	{
		iBookDownloadInfodb->getdatacursordata(iBookDownloadInfodb,(void**)&val,&len);
		if(val&&len)
		{
			if(ReadOneDonwloadInfo(val,len,download_operator))
			{
			IBookDownloadManager_AddOldTask(thiz,(void*)(&download_operator),(unsigned short*)L".mp3");				
			}	
		}
		iBookDownloadInfodb->movedatacursornext(iBookDownloadInfodb);
	}
	iBookDownloadInfodb->unmapdata(iBookDownloadInfodb);
}

void CQDownloadStoreFile::PutDownloadInfoList(addon_llist_ptr_t work_list_data)
{
	if(!work_list_data)
		return;
	
	addon_llink_ptr_t curr = work_list_data->head;
	download_item_ptr_t node = NULL;
	download_operator_data_ptr_t task_data = NULL;

	if(curr)
		node = (download_item_ptr_t)ADDON_CONTAINER_OF( curr, download_item_t, link );

	if(node && node->task)
		task_data = (download_operator_data_ptr_t)ADDON_GET_DATA(node->task);

	if(task_data )
	{
		do 
		{

			PutDownloadInfoData(iBookDownloadInfodb,*task_data);
			node = NULL;
			task_data = NULL;
			curr = curr->next;
			if(curr)
				node = (download_item_ptr_t)ADDON_CONTAINER_OF( curr, download_item_t, link );

			if(node && node->task)
				task_data = (download_operator_data_ptr_t)ADDON_GET_DATA(node->task);

		} while(task_data);
	}
}
//#endif  //#ifndef TESTDOWNLOADCOMPONENT

void CQDownloadStoreFile::RemoveAllDownloadInfoList()
{
	if(iBookDownloadInfodb)
		iBookDownloadInfodb->removeall(iBookDownloadInfodb);	
}

void CQDownloadStoreFile::RemoveOneDownloadInfoList(const unsigned short* filename)
{
	const unsigned short* pKey = filename;
	unsigned int keylen = cx_strlen_w(filename)*2;
	if(iBookDownloadInfodb)
		iBookDownloadInfodb->remove(iBookDownloadInfodb,pKey,keylen);	
}

CQWString CQDownloadStoreFile::GetFilePath()
{
	CQWString str;
	CQSString strRootPath;
	//char disc = CSystemCall::GetInstallDisc();
	//QCHAR sTmp[512];
	//cx_memset(sTmp,0,512);	
	QCHAR *sTmp = (QCHAR *)cx_malloc(512*sizeof(QCHAR));
	cx_memset(sTmp,0,512*sizeof(QCHAR));


	//QCHAR sAppRoot[512];
    //cx_memset(sAppRoot,0,512);
	QCHAR *sAppRoot = (QCHAR *)cx_malloc(512*sizeof(QCHAR));
	cx_memset(sAppRoot,0,512*sizeof(QCHAR));
    CQInstance::GetConfDataRoot(sAppRoot);    
    //cx_strcat_a(sAppRoot,"\\data\\QQReader\\");	

	//const char KReaderSettingFile[] = ":\\data\\QQReader\\ReaderSetting.conf";

	//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KQQBookDir);	
	switch (iDirType)
	{
	case E_MYSHELF_BOOK_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KRecentBookListFile);
		//SPRINTF(sTmp,"%c%s", disc, KRecentBookListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KRecentBookListFile);
		break;
   
	case E_READER_SETTING:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KReaderSettingFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KReaderSettingFile);
		break;
		
	case E_READER_SEARCH_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KSearchListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KSearchListFile);
		break;
//	case E_READER_BOOK_MARK_LIST:
//		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KBookMarkListFile);
//		SPRINTF(sTmp,"%s%s", sAppRoot, KBookMarkListFile);
//		break;
	case E_READER_BOOK_CHAPTER_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KBookChapterListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KBookChapterListFile);
		break;
	case E_READER_WORK_DOWNLOAD_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KWorkDownloadListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KWorkDownloadListFile);
		break;
	case E_READER_DONE_DOWNLOAD_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KDoneDownloadListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KDoneDownloadListFile);
		break;
	case E_READER_ONLINE_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KBookOnlineListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KBookOnlineListFile);
		break;
	case E_READER_CACHE_FILE_LIST:
		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KBookCacheFileListFile);
		SPRINTF(sTmp,"%s%s", sAppRoot, KBookCacheFileListFile);
		break;		
		
// 	case E_COMMEN:
// 	default:
// 		SPRINTF(sTmp,"%c%s", disc, KQQBookDir);
// 		//CBaseUtil::FormatString(strRootPath, "%c%s", disc, KQQBookDir);
// 		//return str;
	}
	
	strRootPath.SetData((QCHAR*)sTmp);	
	
	str = strRootPath;

	cx_free(sAppRoot);
	cx_free(sTmp);
	return str;
}
